from random import randint import sys from flag import flag
defdie(*args): pr(*args) quit()
defpr(*args): s = " ".join(map(str, args)) sys.stdout.write(s + "\n") sys.stdout.flush()
defsc(): return sys.stdin.buffer.readline()
defdid(n, l, K, A): A, K = set(A), set(K) R = [pow(_, 2, n) + randint(0, 1) for _ in A - K] return R
defmain(): border = "+" pr(border*72) pr(border, ".:: Hi all, she DID it, you should do it too! Are you ready? ::. ", border) pr(border*72)
_flag = False n, l = 127, 20 N = set(list(range(0, n))) K = [randint(0, n-1) for _ in range(l)] cnt, STEP = 0, 2 * n // l - 1 whileTrue: ans = sc().decode().strip() try: _A = [int(_) for _ in ans.split(',')] if len(_A) <= l and set(_A).issubset(N): DID = did(n, l, K, _A) pr(border, f'DID = {DID}') if set(_A) == set(K): _flag = True else: die(border, 'Exception! Bye!!') except: die(border, 'Your input is not valid! Bye!!') if _flag: die(border, f'Congrats! the flag: {flag}') if cnt > STEP: die(border, f'Too many tries, bye!') cnt += 1
# context.log_level = 'debug' whileTrue: sh = remote("00.cr.yp.toc.tf",11337) sh.recvuntil("ready?") sh.recvuntil("+++\n") n=127 A = [] for l in range(11): for _ in range(1): reques = ','.join(str( (_ + 15*l)%127) for _ in range(0,20)) sh.sendline(reques) sh.recvuntil("+ DID = ") res = sh.recvuntil("\n")[:-1] res = eval(res) #print(res) for tries in [(_ + 15*l)%127for _ in range(0,20)]: if (pow(tries,2,n) notin res) and (pow(tries,2,n)+1notin res) and tries notin A: A.append(tries) print(len(A),A) if len(A) == 20: reques = ','.join(str(_) for _ in A) sh.sendline(reques) sh.interactive() sh.close() + DID = [] + Congrats! the flag: CCTF{W4rM_Up_CrYpt0_Ch4Ll3n9e!!}
for i in range(1,256): for j in range(256): e = (128<<8)+i try: tmpc = (c<<8)+j d = inverse(e,phi) m = int(pow(tmpc,d,n)) if m<2^200: print(long_to_bytes(m)) except: pass
defgen_seed(s): i, j, k = 0, len(s), 0 while i < j: k = k + ord(s[i]) i += 1 i = 0 while i < j: if (i % 2) != 0: k = k - (ord(s[i]) * (j - i + 1)) else: k = k + (ord(s[i]) * (j - i + 1)) k = k % 2147483647 i += 1
k = (k * j) % 2147483647 return k
defreseed(s): return s * 214013 + 2531011
defencrypt(s, msg): assert s <= 2**32 c, d = 0, s enc, l = b'', len(msg) while c < l: d = reseed(d) enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big') c += 1 return enc
defmul_barak(m, P, E): if P == (0, 0): return P R = (0, 0) while m != 0: if m & 1: R = add_barak(R, P, E) m = m >> 1 if m != 0: P = add_barak(P, P, E) return R
defrand_barak(E): c, d, p = E whileTrue: y = randint(1, p - 1) K = Zmod(p) P.<x> = PolynomialRing(K) f = x**3 - d*x*y + c + y^3 R = f.roots() try: r = R[0][0] return (r, y) except: continue
p = 73997272456239171124655017039956026551127725934222347 d = 68212800478915688445169020404812347140341674954375635 c = 1 E = (c, d, p)
P = rand_barak(E)
FLAG = flag.lstrip(b'CCTF{').rstrip(b'}') m = bytes_to_long(FLAG) assert m < p Q = mul_barak(m, P, E) print(f'P = {P}') print(f'Q = {Q}')
m = 1780694557271320552511299360138314441283923223949197 o = int(P.order()) whileTrue: m+=o if all( 30<x<125for x in long_to_bytes(int(m))): print(long_to_bytes(int(m))) break
sage: E Scheme morphism: From: Projective Plane Curve over Ring of integers modulo 73997272456239171124655017039956026551127725934222347 defined by x^3 + y^3 + 5784471977323482679485996635143679410786050979846712*x*y*z + z^3 To: Elliptic Curve defined by y^2 + 41848246294228984089267712788268151466593112763848031*x*y = x^3 + 8186198475255690096811875068967290988967924587416530*x^2 + 67041837351181533250843830910913901867849396421579685*x + 40673641660869730385035838198800394713965979400200155 over Ring of integers modulo 73997272456239171124655017039956026551127725934222347 Defn: Defined on coordinates by sending (x : y : z) to (9167218108590654299487009181696317855454416112239889*y + 3279765642505352830157211697766991850038465138705271*z : 5784471977323482679485996635143679410786050979846712*y : 64249990329941531194735759683164021211133831031453155*x + 22688267644108754864364901498104863155005679028019334*y + 42580013058247064141816874924090310799821854717107287*z)
from Crypto.Util.number import * from secret import m, flag
defgenPrime(m, nbit): assert m >= 2 whileTrue: a = getRandomNBitInteger(nbit // m) r = getRandomNBitInteger(m ** 2 - m + 2) p = a ** m + r if isPrime(p): return (p, r)
defgenkey(m, nbit): p, r = genPrime(m, nbit // 2) q, s = genPrime(m, nbit // 2) n = p * q e = r * s return (e, n)
defencrypt(msg, pkey): e, n = pkey m = bytes_to_long(msg) c = pow(m, e, n) return c
from gmpy2 import * from sympy import isprime n=373824666550208932851344358703053061405262438259996622188837935528607451817812480600479188884096072016823491996056842120586016323642383543231913508464973502962030059403443181467594283936168384790367731793997013711256520780338341018619858240958105689126133812557401122953030695509876185592917323138313818881164334490044163316692588337720342646339764174333821950301279825316497898035760524780198230860089280791887363472060435443944632303774987556026740232641561706904946900169858650106994947597642013168757868017723456208796677559254390940651802333382820063200360490892131573853635471525711894510477078934343423255983
ab = int(iroot(n,4)[0]) ab4 = ab^4
rs = 150953688 for r in rs.divisors(): s = rs//r c = n-ab4-rs delta = c^2-4*rs*ab4 sdelta = int(iroot(delta,2)[0]) a4 = (c+sdelta)//(2*s) if iroot(a4,4)[1]: a = int(iroot(a4,4)[0]) b = int(iroot(ab4,4)[0]//a) if isprime(a^4+r): print("[+] p=",a^4+r) print("[+] q=",n//(a^4+r)) elif isprime(a^4+s): print("[+] p=",a^4+s) print("[+] q=",n//(a^4+s)) [+] p= 24854995563762799317055160315647073592768859410925406616067526817964296709994775588158311030813096922905657553370793515214591086698010302872311633588541111630338981703494212247996116660819640489213219705595382514374022123356637290058228183400682431815794876393612877273757515867990847040787313812864434536969 [+] q= 15040222622096320078383580808680733765955114958694997949647342925417877088612792495485641348591026281373930569798925789027166056695954731923306109646611840570310396750856642056018981080439916663195842593441587057719678555907050674529272376248049062724657792390788687452049496308886252188791975094655675938807
import random import time from tqdm import tqdm from Crypto.Util.number import * # About 3 seconds to run defAMM(o, r, q): start = time.time() print('\n----------------------------------------------------------------------------------') print('Start to run Adleman-Manders-Miller Root Extraction Method') print('Try to find one {:#x}th root of {} modulo {}'.format(r, o, q)) g = GF(q) o = g(o) p = g(random.randint(1, q)) while p ^ ((q-1) // r) == 1: p = g(random.randint(1, q)) print('[+] Find p:{}'.format(p)) t = 0 s = q - 1 while s % r == 0: t += 1 s = s // r print('[+] Find s:{}, t:{}'.format(s, t)) k = 1 while (k * s + 1) % r != 0: k += 1 alp = (k * s + 1) // r print('[+] Find alp:{}'.format(alp)) a = p ^ (r**(t-1) * s) b = o ^ (r*alp - 1) c = p ^ s h = 1 for i in range(1, t): d = b ^ (r^(t-1-i)) if d == 1: j = 0 else: print('[+] Calculating DLP...') j = - discrete_log(d, a) print('[+] Finish DLP...') b = b * (c^r)^j h = h * c^j c = c^r result = o^alp * h end = time.time() print("Finished in {} seconds.".format(end - start)) print('Find one solution: {}'.format(result)) return result
defonemod(p,r): t=random.randint(2,p) while pow(t,(p-1)//r,p)==1: t=random.randint(2,p) return pow(t,(p-1)//r,p) defsolution(p,root,e): whileTrue: g=onemod(p,e) may=[] for i in tqdm(range(e)): may.append(root*pow(g,i,p)%p) if len(may) == len(set(may)): return may
defsolve_in_subset(ep,p): cp = int(pow(c,inverse(int(e//ep),p-1),p)) com_factors = [] while GCD(ep,p-1) !=1: com_factors.append(GCD(ep,p-1)) ep //= GCD(ep,p-1) com_factors.sort()
cps = [cp] for factor in com_factors: mps = [] for cp in cps: mp = AMM(cp, factor, p) mps += solution(p,mp,factor) cps = mps for each in cps: assert pow(each,e,p)==c%p return cps
p = 24854995563762799317055160315647073592768859410925406616067526817964296709994775588158311030813096922905657553370793515214591086698010302872311633588541111630338981703494212247996116660819640489213219705595382514374022123356637290058228183400682431815794876393612877273757515867990847040787313812864434536969 q = 15040222622096320078383580808680733765955114958694997949647342925417877088612792495485641348591026281373930569798925789027166056695954731923306109646611840570310396750856642056018981080439916663195842593441587057719678555907050674529272376248049062724657792390788687452049496308886252188791975094655675938807 e = 150953688 c = 275574424285842306309073814038154403551700455145115884031072340378743712325975683329051874910297915882286569143815715537085387363420246497061870251520240399514896001311724695996978111559476733709139080970977190150345474341853495386364275702356438666152069791355990718058189043717952080875207858163490627801836274404446661613239167700736337269924479349700031535265765885064606399858172168036794462235707003475360358004643720927563261787867952228496769300443415094124132722170498229611285689671203272698693505808912907778910378274197503048226322090611405601517624884408718689404556983397217070272851442351897456769883
start = time.time() print('Start CRT...') for mpp in m_p: for mqq in m_q: solution = CRT_list([int(mpp), int(mqq)], [p, q]) if solution < 2^800 : # Always the bit_length of flag is less than 800 print(long_to_bytes(solution))
end = time.time() print("Finished in {} seconds.".format(end - start))
from Crypto.Util.number import * from pyope.ope import OPE as enc from pyope.ope import ValueRange import sys from secret import key, flag
defdie(*args): pr(*args) quit()
defpr(*args): s = " ".join(map(str, args)) sys.stdout.write(s + "\n") sys.stdout.flush()
defsc(): return sys.stdin.buffer.readline()
defencrypt(msg, key, params): if len(msg) % 16 != 0: msg += (16 - len(msg) % 16) * b'*' p, k1, k2 = params msg = [msg[_*16:_*16 + 16] for _ in range(len(msg) // 16)] m = [bytes_to_long(_) for _ in msg] inra = ValueRange(0, 2**128) oura = ValueRange(k1 + 1, k2 * p + 1) _enc = enc(key, in_range = inra, out_range = oura) C = [_enc.encrypt(_) for _ in m] return C
defmain(): border = "|" pr(border*72) pr(border, " Welcome to Roldy combat, we implemented an encryption method to ", border) pr(border, " protect our secret. Please note that there is a flaw in our method ", border) pr(border, " Can you examine it and get the flag? ", border) pr(border*72)
那么我们来简单看一下这个 OPE,直接去pypi看,其中提到 This is an implementation of Boldyreva symmetric order-preserving encryption scheme (Boldyreva’s paper). 这是一种保序加密的实现,那么何为”保序“呢?下面给出了例子
''' # https://github.com/mimoo/RSA-and-LLL-attacks/blob/master/boneh_durfee.sage ''' defexample(): ############################################ # How To Use This Script ##########################################
# # The problem to solve (edit the following values) #
# the modulus N = 12765231982257032754070342601068819788671760506321816381988340379929052646067454855779362773785313297204165444163623633335057895252608396010414744222572161530653104640020689896882490979790275711854268113058363186249545193245142912930804650114934761299016468156185416083682476142929968501395899099376750415294540156026131156551291971922076435528869024742993840057342092865203064721826362149723366381892539617642364692012936270150691803063945919154346756726869466855557344213050973081755499746750276623648407677639812809665472258655462846021403503851719008687214848550916999977775070011121527941755954255781343103086789 # the public exponent e = 459650454686946706615371845737527916539205656667844780634386049268800615782964920944229084502752167395446158290854047696006034750210758341744841762479191173017773034647739346927390580848998121830029134542880713409306092967282675122699586503684943407535067216738556403169403622104762516293879994387324370835718056251706150557820106296417750402984941838652433642298378976899556042987560946508887315484380807248331504458640857234708123277403252632993828101306072382329879857946191508782246793011691530554606521701055094223574951862129713872918021549814674387049788995785872980320871421550616327471735316980754238323013
# the hypothesis on the private exponent (the theoretical maximum is 0.292) delta = .291# this means that d < N^delta
# # Lattice (tweak those values) #
# you should tweak this (after a first run), (e.g. increment it until a solution is found) m = 6# size of the lattice (bigger the better/slower)
# you need to be a lattice master to tweak these t = int((1-2*delta) * m) # optimization from Herrmann and May X = 2*floor(N^delta) # this _might_ be too much Y = floor(N^(953/2048)) # correct if p, q are ~ same size
# # Don't touch anything below #
# Problem put in equation P.<x,y> = PolynomialRing(ZZ) pbar = int('10100000111001001100001011000110111010001101001011000110110000101101100',2)<<(1024-71) A = int((N+1-2*pbar)/2) pol = 1 + x * (A + y)
# # Find the solutions! #
# Checking bounds if debug: print("=== checking values ===") print("* delta:", delta) print("* delta < 0.292", delta < 0.292) print("* size of e:", int(log(e)/log(2))) print("* size of N:", int(log(N)/log(2))) print("* m:", m, ", t:", t)
from Crypto.Util.number import * n = (112427415074496733728692221822236708267020071361134595480944452567332776053338591808303191116824668207575885357243149596990683319683952721613109860104563666843168030575222891621946617002107610348479917006441273131192536638336531098426557725336808479141871883466571954197021295145182566118601456967383373633195241318527152234920928439522439998675385534769566753824107447367198956368408576813105163823071250689597585130857134935943413570763481702219998410358821249192007224259883929235667449109565875403158782316445806131091179344390038436184567391800053904246077478412520806972604858022406108303505402566299783227719)<<8
candidate_n=[] for i in range(256): for each in sieve_base: if (n+i)%each == 0: break else: candidate_n.append(n+i) print(len(candidate_n)) #18
defwiener(e, n): # Convert e/n into a continued fraction cf = continued_fraction(e/n) convergents = cf.convergents() for kd in convergents: k = kd.numerator() d = kd.denominator() # Check if k and d meet the requirements if k == 0or d%2 == 0or e*d % k != 1: continue phi = (e*d - 1)/k # Create the polynomial x = PolynomialRing(RationalField(), 'x').gen() f = x^2 - (n-phi+1)*x + n roots = f.roots() # Check if polynomial as two roots if len(roots) != 2: continue # Check if roots of the polynomial are p and q p,q = int(roots[0][0]), int(roots[1][0]) if p*q == n: return d returnNone # Test to see if our attack works
for n in candidate_n: for i in range(1,256,2): e = (ebar << 8) + i d = wiener(e,n) if d: for j in range(256): c = (cbar<<8)+j m = int(pow(c,d,n)) if m.bit_length()<800: print(long_to_bytes(int(pow(c,d,n))).decode())
import os from hashlib import md5 from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from PIL import Image from PIL import ImageDraw from flag import flag
key = get_random_bytes(8) * 2 iv = md5(key).digest()
bkcrack 1.5.0 - 2023-07-12 [04:03:32] Recovering password length10... Password: �n�y*�Z��n (asbytes: ad 6e fb 792a ea 5a aa ad 6e) Somecharactersarenotin the expected charset. Continuing. 100.0 % (65536 / 65536) [04:03:35] Could notrecoverpassword
解密压缩包得到图片
编写解密代码解密密文获得 flag
1 2 3 4 5 6 7 8 9 10 11 12 13
import os from hashlib import md5 from Crypto.Cipher import AES
key = b"\xad\x6e\xfb\x79\x2a\xea\x5a\xaa" * 2 iv = md5(key).digest()
from Crypto.Util.number import * from flag import flag
defbase(n, l): D = [] while n > 0: n, r = divmod(n, l) D.append(r) return''.join(str(d) for d in reversed(D)) or'0'
defasiv_prng(seed): l = len(seed) _seed = base(bytes_to_long(seed), 3) _seed = [int(_) for _ in _seed] _l = len(_seed) R = [[getRandomRange(0, 3) for _ in range(_l)] for _ in range(_l**2)] S = [] for r in R: s = 0 for _ in range(_l): s += (r[_] * _seed[_]) % 3 # s += getRandomRange(0, 3) s %= 3 S.append(s) return R, S
seed = flag.lstrip(b'CCTF{').rstrip(b'}') R, S = asiv_prng(seed)
f = open('output.txt', 'w') f.write(f'R = {R}\nS = {S}') f.close()
题目首先将 flag 转为三进制,随后作为 seed 数组,然后根据 _seed 数组的长度随机生成了一系列随机数组 R,然后对每一个 R 数组做运算 $$ s \equiv \sum{i=0}^{n}r_i \cdot seed_i \pmod 3 $$ 题目给出了 R 数组和由 s 组成的 S 数组,所以其实就是在模 3 下解一个线性同余方程组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
from Crypto.Util.number import *
with open("output.txt ") as f: data = f.read().split("\n")
R = eval(data[0][4:]) S = eval(data[1][4:]) RR = matrix(Zmod(3),R[:200]) SS = vector(Zmod(3),S[:200]) mm = RR.solve_right(SS)
flag = ''.join(str(i) for i in mm) flag = int(flag,3) print(long_to_bytes(flag))
# b'3Xpl0i7eD_bY_AtT4ck3r!'
TPSD
1 2 3 4 5 6 7 8 9 10 11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Welcome, esteemed cryptographers with expertise innumber theory! + + It's a pleasure to have you here. Whether you're a seasoned veteran + + or a budding enthusiast, let's dive inand explore the fascinating + + world of cryptography andnumber theory together! + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + We are looking fortheinteger solution of p^3 + q^3 + r^3 = 1, such + + thatat least one of p, q, or r is prime. Submit each such triple + + atevery step with mentioned properties. + + Send a triple array of integers whose absolute minimum value has + + almost (6, 26)-bits. You are at level 1:
import random from pwn import * from Crypto.Util.number import * from sympy import * context.log_level = 'debug'
sh = remote("05.cr.yp.toc.tf","11137") whileTrue: sh.recvuntil("+ almost (") l = int(sh.recvuntil(", ")[:-2]) h = int(sh.recvuntil(")")[:-1]) whileTrue: t = random.randint(2**(l//3),2**(h//3)) r = -9*t**3+1 if isprime(abs(r)) and (2**l)<abs(r)<(2**h):
break p = 9*t**4 q = -9*t**4+3*t sh.recvuntil("level") sh.recvuntil(": \n") sh.sendline(','.join(str(i) for i in [p,q,r]))
b'+ gj, try the next level :)\n' b'+ Send a triple array of integers whose absolute minimum value has +\n' b'+ almost (186, 206)-bits. You are at level 19: \n' [DEBUG] Sent 0xe7 bytes: b'2610575330510601411661135837391203680216386303602680076369749905572234291076173824,-2610575330510601411661135837391203680216386303602680076369749514060588681431841560,-20003813626888652657280145082395768211458812516684950505205247\n' [DEBUG] Received 0x3f bytes: b'+ Congrats! the flag: CCTF{pr1m3S_in_7ErnArY_Cu8!c_3qu4tI0nS!}\n'
defpr(*args): s = " ".join(map(str, args)) sys.stdout.write(s + "\n") sys.stdout.flush()
defsc(): return sys.stdin.buffer.readline()
defcheck_inputs(a, b, c): ifnot all(isinstance(x, int) for x in [a, b, c]): returnFalse if a == 0or b == 0or c == 0: returnFalse if a == b or b == c or a == c: returnFalse returnTrue
defmain(): border = "|" pr(border*72) pr(border, ".:: Hi all, she DID it, you should do it too! Are you ready? ::. ", border) pr(border, "Welcome to the Ternary World! You need to pass each level until 20 ", border) pr(border, "to get the flag. Pay attention that your solutions should be nonzero", border) pr(border, "distinct integers. Let's start! ", border) pr(border*72)
level, step = 0, 19 while level <= step: a = random.randint(2**(level * 12), 2**(level*12 + 12)) equation = f'x^2 + y^2 - xy = {a}*z^3' pr(f"Level {level + 1}: {equation}") inputs = input().strip().split(",") try: x, y, z = map(int, inputs) except: die(border, "Invalid input, Bye!!") if check_inputs(x, y, z): if check_solution(a, x, y, z): pr(border, "Correct! Try the next level :)") level += 1 else: pr(border, "You didn't provide the correct solution.") die(border, "Better luck next time!") else: pr(border, "Your solutions should be non-zero distinct integers") die(border, "Quiting...") if level == step: pr(border, "Congratulations! You've successfully solved all the equations!") die(border, f"flag: {flag}")
xp = (m**3 + a*m + b) % p 这里首先将 flag 放在了一条椭圆曲线上,作为 x 轴坐标 ,并且分别是在子群 p,q 下进行计算的。所以在后面使用了中国剩余定理来计算模 n 下曲线的 y 点,x = (Z(rp) * Z(q) * Z(y) + Z(rq) * Z(p) * Z(x)) % n
A = p-_s n=6660938713055850877314255610895820875305739186102790477966786501810416821294442374977193379731704125177528590285016474818841859956990486067573436301232301 # f = 2p^2-p(2A-a)-n for a in range(99999): delta = (2*A-a)**2+4*2*n if iroot(delta,2)[1]: delta = iroot(delta,2)[0] p = ((2*A-a)+delta)//4 assert n%p==0 print(p) print(n//p)
p = 93511613846272978051774379195449772332692693333173612296021789501865098047641 q = 71231138455229760679977773382211636812795966734548537479512744210680602878261 a = 5539256645640498184116966196249666621079506508209770360679460869295427007578 b = 20151017657582479433586370393795140515103572865771721775868586710594524816458 Q = (6641320679869421443758875467781930795132746694454926965779628505713445486895274490835545942727970688359873955019634877304270220728625521646208912044469433,2856872654927815636828860866843721158889474116106462420201092148493803550131351543372740950198853438539317164093538508795630146854596724019329887894933972)
import sys import math import functools from PIL import Image from random import randint import string from secret import flag, key, n
defpad(s, l): while len(s) < l: s += string.printable[randint(0, 61)] return s
defsox(n, d): x, y, t = 0, 0, d for s in range(n - 1): u = 1 & t // 2 v = 1 & t ^ u x, y = spin(2**s, x, y, u, v) x += 2**s * u y += 2**s * v t = t // 4 return x, y
defspin(n, x, y, u, v): if v == 0: if u == 1: x = n - 1 - x y = n - 1 - y x, y = y, x return x, y
defencrypt(msg, key, n): _msg = pad(msg, n ** 2) _msg, _key = [ord(_) for _ in _msg], [ord(_) for _ in key] img = Image.new('RGBA', (n, n), 'darkblue') pix = img.load()
for _ in range(len(key)): w = len(_key) h = n**2 // w + 1 arr = [[_msg[w*x + y] if w*x + y < n**2elseNonefor x in range(h)] for y in range(w)] _conf = sorted([(_key[i], i) for i in range(w)]) _marshal = [arr[_conf[i][1]] for i in range(w)] _msg = functools.reduce(lambda a, r: a + _marshal[r], range(w), []) _msg = list(filter(lambda x: x isnotNone, _msg)) _msg = [(_msg[_] + _key[_ % w]) % 256for _ in range(n**2)]
for d in range(n**2): x, y = sox(n, d) pix[x,y] = (_msg[d], _msg[d], _msg[d]) keysum = sum(_key) if w > 0else0 orient = keysum % 4 img = img.rotate(90*orient) return img
这道题目将 flag 的信息储存在了图片中,出题人对 python 语言的娴熟操作也令整个代码读起来会略微有点吃力,需要静下心来慢慢分析。我们先看到 encrypt 这个函数,
1 2 3 4 5
_msg = pad(msg, n ** 2) _msg, _key = [ord(_) for _ in _msg], [ord(_) for _ in key] img = Image.new('RGBA', (n, n), 'darkblue') pix = img.load() for _ in range(len(key)):
首先创建了一个 $n\times n$ 的图片,然后将 flag 填充至 $n\times n$ 的长度,随后分别用每个密钥进行处理,密钥未知,但是密钥的长度为3,并且使用了 ord 函数,说明每个密钥的值得范围是 $0-255$。
1 2 3
w = len(_key) h = n**2 // w + 1 arr = [[_msg[w*x + y] if w*x + y < n**2elseNonefor x in range(h)] for y in range(w)]
# https://blog.maple3142.net/2023/07/09/cryptoctf-2023-writeups/#bertrand import sys import math import functools from PIL import Image from random import randint import string import itertools import z3
defpad(s, l): while len(s) < l: s += string.printable[randint(0, 61)] return s
defsox(n, d): x, y, t = 0, 0, d for s in range(n - 1): u = 1 & t // 2 v = 1 & t ^ u x, y = spin(2**s, x, y, u, v) x += 2**s * u y += 2**s * v t = t // 4 return x, y
defspin(n, x, y, u, v): if v == 0: if u == 1: x = n - 1 - x y = n - 1 - y x, y = y, x return x, y
n = 256 img = Image.open("enc.png") img = img.rotate(90 * 1) # guess pix = img.load() msg = [] for d in range(n**2): x, y = sox(n, d) msg.append(pix[x, y][0])
deftry_conf(conf): key_sym = [z3.BitVec("key_%d" % i, 8) for i in range(3)] msg_sym = [z3.BitVec("msg_%d" % i, 8) for i in range(n**2)] msg_arr = msg_sym[:] for _ in range(len(key_sym)): w = len(key_sym) h = n**2 // w + 1 arr = [[msg_arr[w * x + y] if w * x + y < n**2elseNonefor x in range(h)] for y in range(w)] _marshal = [arr[conf[i]] for i in range(w)] msg_arr = functools.reduce(lambda a, r: a + _marshal[r], range(w), []) msg_arr = list(filter(lambda x: x isnotNone, msg_arr)) msg_arr = [(msg_arr[_] + key_sym[_ % w]) % 256for _ in range(n**2)] sol = z3.Solver() for i in range(n**2): sol.add(msg_arr[i] == msg[i]) for x, y in zip(msg_sym, b"CCTF{"): sol.add(x == y) if sol.check() == z3.sat: m = sol.model() print([m.eval(x) for x in key_sym]) print(bytes([m.eval(x).as_long() for x in msg_sym])[:100])
for conf in itertools.permutations(range(3)): # correct conf = (1, 2, 0) print(conf) try_conf(conf)
from Crypto.Util.number import * from hashlib import sha512 from flag import flag
defgenkey(nbit): whileTrue: p = getPrime(nbit) if p % 4 == 3: q = int(str(p)[::-1]) if isPrime(q): return p * q, (p, q)
defsetup(msg, pkey): hid = sha512(msg).digest() whileTrue: a = bytes_to_long(hid) if kronecker(a, pkey) == 1: return a else: hid = sha512(hid).digest()
defencrypt(msg, pkey): a, m = setup(msg, pkey), bytes_to_long(msg) B, C = bin(m)[2:], [] for b in B: whileTrue: t = randint(1, pkey) if kronecker(t, pkey) == 2 * int(b) - 1: C.append((t - a * inverse(t, pkey)) % pkey) break return (a, C)
pkey, privkey = genkey(512) E = encrypt(flag, pkey)
from Crypto.Util.number import * from random import randint from math import * # https://kt.gy/blog/2015/10/asis-2015-finals-rsasr/
deft(a, b, k): # sqrt(n) has 154 digits, so we need to figure out 77 digits on each side if k == (ndigs+1)//2: if a*b == n: print('p = %d' % a) print('q = %d' % b) return for i in range(10): for j in range(10): # we try to guess the last not-already-guessed digits of both primes a1 = a + i*(10**k) + j*(10**(ndigs-k)) b1 = b + j*(10**k) + i*(10**(ndigs-k)) if a1*b1 > n: # a1 and b1 are too large continue if (a1+(10**(ndigs-k)))*(b1+(10**(ndigs-k))) < n: # a1 and b1 are too small continue if ((a1*b1)%(10**(k+1))) != (n%(10**(k+1))): # The last digits of a1*b1 (which won't change later) doesn't match n continue # this a1 and b1 seem to be a possible match, try to guess remaining digits t(a1, b1, k+1)
n = 72271787633166084700895603235291055045699965307538401174867474485084272711938364003794151073975875159886045553516299177522950407802715116792937858353646755246888532333536918663888208381012106370000886903776721867958523682675624556576505534100750339626081218194389244007622749982917071344697799413034317147013 ndigs = len(str(isqrt(n)))-1 t(0, 0, 0)
p = 7690745050590286968025665448815927548186441771518218204702842288098845344789340509868897149374937793107491606741591691437711395848517107039674900831427939 q = 9397241380094769307017158485931177341961951476061947013977394739417988689050439874435488908822482074028128151771446818457295188445665208696820950505470967
whileTrue: p = getPrime(128) q = getPrime(128) pkey = p*q if p%4==3and q%4==3: break
defqsqrt(s,p): return pow(s,(p+1)//4,p)
whileTrue: a = randint(1, pkey) if kronecker(a, pkey) == 1: break
for _ in range(100): t = randint(1, pkey) if kronecker(t, pkey) == 1: c =(t - a * inverse(t, pkey)) % pkey tp = (qsqrt(c^2+4*a,p)+c)/2 tq = (qsqrt(c^2+4*a,q)+c)/2 ti = crt([int(tp),int(tq)],[p,q]) print(kronecker(ti, pkey))
p = 9397241380094769307017158485931177341961951476061947013977394739417988689050439874435488908822482074028128151771446818457295188445665208696820950505470967 q = 7690745050590286968025665448815927548186441771518218204702842288098845344789340509868897149374937793107491606741591691437711395848517107039674900831427939 a = 8288287062919561222859437914506472745100526530793196302687340335555115611914901909767968051705772262896385459058120439118678774481183385263128414336707441 C = [...] flag = "" for c in C: tp = (qsqrt(c^2+4*a,p)+c)/2 tq = (qsqrt(c^2+4*a,q)+c)/2 ti = crt([int(tp),int(tq)],[p,q]) flag += "1"if kronecker(ti, p*q)==1else"0" print(long_to_bytes(int(flag,2)))
# b'CCTF{_Cocks_18e_5chEm3}'
Byeween
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[root@VM-0-7-centos 2023CCTF]# nc 03.cr.yp.toc.tf 33137 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | Hi all, I have created a basic and simple cryptography task about | | elliptic curve over rational field. Your mission is to find all | | points Q over E such that 2 * Q = P, such that P is given. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | Generating parameters, please wait... | Options: | [I]informations | [S]ubmit points | [Q]uit I | E = Elliptic Curve defined by y^2 = x^3 - 342446165721*x over Rational Field | Q = (11312349909982661811485861119060804225/19331014841872758669209197674496 : 116099721688697073463805997395884506343692166552542145/84992769577026199814140167579218475635959660544 : 1) | Options: | [I]informations | [S]ubmit points | [Q]uit
s | Please send the points on elliptic curve one by one: -581886118964997/2395417249,-30763025733327911831808/117238906417807 | You have sent 1 correct points already! | Options: | [I]informations | [S]ubmit points | [Q]uit s | Please send the points on elliptic curve one by one: -45549205864448/188320729,677260204084819298944/2584325364067 | You have sent 2 correct points already! | Options: | [I]informations | [S]ubmit points | [Q]uit s | Please send the points on elliptic curve one by one: 5454365075973/3869089,-11589081804276058368/7610498063 | You have sent 3 correct points already! | Options: | [I]informations | [S]ubmit points | [Q]uit s | Please send the points on elliptic curve one by one: 3920272615593/2768896,7067979399917751147/4607442944 | Congrats, you got the flag: b'CCTF{H4lVin9_pO!ntS_0n_3lLipT1C_cuRve5!}'
也许出题人本意是让我们自己实现叭,故放在了 hard 难度,没想到 sagemath 就有现成的实现。
import sys from Crypto.Util.number import * from hashlib import sha256 from flag import flag
p = 114863632180633827211184132915225798242263961691870412740605315763112513729991 A = -3 B = 105675527217961035404524512435875047840495516468907806313576241823653895562912 E = EllipticCurve(GF(p), [A, B]) G = E.random_point() _o = E.order() original_msg = 'I love all cryptographers!!!'
defdie(*args): pr(*args) quit()
defpr(*args): s = " ".join(map(str, args)) sys.stdout.write(s + "\n") sys.stdout.flush()
defencrypt(msg, pkey): e, l = randint(1, _o), len(msg) m1, m2 = bytes_to_long(msg[:l // 2]), bytes_to_long(msg[l // 2:]) assert m1 < p and m2 < p e1, e2 = (e * pkey).xy() c1, c2 = m1 * e1 % p, m2 * e2 % p return (c1, c2, e * G)
defsign(msg, skey): _tail = bytes_to_long(sha256(str(skey).encode('utf-8')).digest()) % (1 << 24) whileTrue: K = [randint(1, 2**255) // (1 << 24) + _tail for _ in'__'] r, s = int((K[0] * G).xy()[0]), int((K[1] * G).xy()[1]) if r * s != 0: break h = bytes_to_long(sha256(msg).digest()) t = inverse(K[0], _o) * (h * r - s * skey) % _o return (r, s, t)
defverify(msg, pkey, _sign): r, s, t = [int(_) % _o for _ in _sign] h = bytes_to_long(sha256(msg.encode('utf-8')).digest()) u = int(h * r * inverse(t, _o) % _o) v = int(s * inverse(t, _o) % _o) # u = h * r * inverse(t, _o) % _o # v = s * inverse(t, _o) % _o _R = (u * G - v * pkey).xy()[0] return _R == r
defmain(): border = "|" pr(border*72) pr(border, "Hi all, now it's time to solve a probably simple ECC challenge about", border) pr(border, "encryption and signing in elliptic curves! Follow the questions and ", border) pr(border, "find the secret flag, are you ready!? ", border) pr(border*72)
pkey, skey = keygen(E)
whileTrue: pr("| Options: \n|\t[E]ncrypt a message! \n|\t[G]et the flag \n|\t[P]ublic Key \n|\t[S]ign a message \n|\t[V]erify signature \n|\t[Q]uit") ans = sc().decode().lower().strip() if ans == 'e': pr(border, 'Send your message here: ') _msg = sc() _enc = encrypt(_msg, pkey) pr(border, f'enc = {_enc}') elif ans == 'g': pr(border, 'You should send the valid signature for my given message!') pr(border, 'Send the signature of original message here: ') _sgn = sc().split(b',') try: _sgn = [int(_) for _ in _sgn] if verify(original_msg, pkey, _sgn): die(border, f'Congratz! You got the flag: {flag}') else: pr(border, 'Your signature is not correct!') except: import traceback; traceback.print_exc() pr(border, 'Try to send valid signature!') continue elif ans == 's': pr(border, 'Send your message to sign: ') _msg = sc() if len(_msg) >= 10: die(border, 'Sorry, I sign only short messages! :/') _sgn = sign(_msg, skey) pr(border, f'sgn = {_sgn}') elif ans == 'v': pr(border, 'Send your signature to verify: ') _sgn = sc().split(b',') try: _sgn = [int(_) for _ in _sgn] pr(border, 'Send your message: ') _msg = sc() if verify(_msg, pkey, _sgn): pr(border, 'Your message successfully verified :)') else: pr(border, 'Verification failed :(') except: pr(border, 'Try to send valid signature!') continue elif ans == 'p': pr(border, f'pkey = {pkey}') pr(border, f'G = {G}') elif ans == 'q': die(border, 'Quitting...') else: die(border, 'You should select valid choice!')
if __name__ == '__main__': main()
题目是基于 ECC 的加密、签名系统,提供四个服务
提供加密服务
提供签名服务,但是签名的数据长度不能超过 10
提供验签服务
如果提供的签名是消息 I love all cryptographers!!! 的签名,则给出 flag。
注意到由于签名服务限制了消息长度,我们无法直接让服务端给我们计算 I love all cryptographers!!! 的签名,那么应该是利用其他服务来获取服务端的私钥,然后自己计算签名。
1 2 3 4 5 6 7
defencrypt(msg, pkey): e, l = randint(1, _o), len(msg) m1, m2 = bytes_to_long(msg[:l // 2]), bytes_to_long(msg[l // 2:]) assert m1 < p and m2 < p e1, e2 = (e * pkey).xy() c1, c2 = m1 * e1 % p, m2 * e2 % p return (c1, c2, e * G)
from hashlib import sha256 from Crypto.Util.number import * context.log_level = 'debug' p = 114863632180633827211184132915225798242263961691870412740605315763112513729991 A = -3 B = 105675527217961035404524512435875047840495516468907806313576241823653895562912 E = EllipticCurve(GF(p), [A, B]) G = E.random_point() o = _o = E.order() original_msg = b'I love all cryptographers!!!'
local = False ifnot local: from pwn import *
sh = remote('06.cr.yp.toc.tf','13337') sh.recvuntil("[Q]uit\n") sh.sendline("P") sh.recvuntil("| pkey = (") x = int(sh.recvuntil(" : ")[:-3]) y = int(sh.recvuntil(" : ")[:-3]) pubkey = E(x,y)
sh.recvuntil("G = (") x = int(sh.recvuntil(" : ")[:-3]) y = int(sh.recvuntil(" : ")[:-3]) G = E(x,y) print(pubkey,G)
defget_sign(msg): sh.recvuntil("[Q]uit\n") sh.sendline("S") sh.recvuntil("sign: ") sh.sendline(msg) sh.recvuntil('sgn = ') sig = eval(sh.recvuntil(")")) return sig
defsign(msg, skey): _tail = bytes_to_long(sha256(str(skey).encode('utf-8')).digest()) % (1 << 24) whileTrue: K = [randint(1, 2**255) // (1 << 24) + _tail for _ in'__'] r, s = int((K[0] * G).xy()[0]), int((K[1] * G).xy()[1]) if r * s != 0: break h = bytes_to_long(sha256(msg).digest()) t = inverse(K[0], _o) * (h * r - s * skey) % _o return (r, s, t)
A = [] B = [] times = 0 while len(A)<40: print(len(A)) try: times+=1 ifnot local: r,s,t = get_sign(str(times).encode()) else: r,s,t = sign(str(times).encode(),skey) h = bytes_to_long(sha256((str(times)+"\n").encode('utf-8')).digest()) # 这里好坑,我卡了好久,本地都能成功,远程就是失败,一直找不到原因,最后才意识到可能是 hash 算错了。 A.append(int((-inverse(t,o)*s)%o)) B.append(int(inverse(t,o)*h*r%o)) except Exception as e: print(str(e)) pass
print("construct hnp lattice...") CC = matrix(QQ,[A,B]) K = 2^232 DD = matrix(QQ,[[K/o,0],[0,K]]) MM = block_matrix(QQ,[[o,0],[CC,DD]]) L = MM.LLL()
for each in L: if abs(each[-1]) == K: if each[-2] * o % K == 0: print(each) ss = (each[-2] * o // K)%o # skey = abs(skey) print(pubkey == ss*G) signatrue = sign(original_msg, ss) sh.recvuntil("[Q]uit\n") sh.sendline("G") sh.recvuntil("message here: ") sh.sendline(','.join(str(i)for i in signatrue)) sh.interactive()
# print(int(each[0]).bit_length(),skey) [DEBUG] Received 0x46 bytes: b"| Congratz! You got the flag: b'CCTF{L4T71c3_atTAck5_a9A!nS7_ECDSA!}'\n" | Congratz! You got the flag: b'CCTF{L4T71c3_atTAck5_a9A!nS7_ECDSA!}'
import sys import random import binascii from flag import flag
defdie(*args): pr(*args) quit()
defpr(*args): s = " ".join(map(str, args)) sys.stdout.write(s + "\n") sys.stdout.flush()
defsc(): return sys.stdin.buffer.readline()
defvinefruit(msg, mod, flag = 0): P = [16777619, 1099511628211, 309485009821345068724781371] O = [2166136261, 14695981039346656037, 144066263297769815596495629667062367629] assert mod in [0, 1, 2] p, o, m = P[mod], O[mod], 2 ** (2 << (4 + mod)) vine = o for b in msg: if flag == 1: vine = (vine + b) % (2 ** 128) else: vine = vine ^ b vine = (vine * p) % m return vine
defmain(): border = "|" pr(border*72) pr(border, " Hi all, I have designed a gorgeous cryptography hash function in ", border) pr(border, " order to secure the world! Your mission is to find collision for ", border) pr(border, " this function with specific conditions. ", border) pr(border*72) step = 19
whileTrue: pr("| Options: \n|\t[S]ubmit collision \n|\t[Q]uit") ans = sc().decode().lower().strip() if ans == 's': S = [] for level in range(step): mod = random.randint(0, 2) pr(border, f'Submit two different string such that vinefruit(m1, {mod}, 1) = vinefruit(m2, {mod}, 1)') pr(border, f'You are at level: {level + 1}') if level == step - 1and len(S) == step - 1: die(border, f'Congrats, you got the flag: {flag}') try: pr(border, f'Please send first byte string: ') s1 = sc()[:-1] pr(border, f'Please send second byte string: ') s2 = sc()[:-1] s1, s2 = binascii.unhexlify(s1), binascii.unhexlify(s2) except: pr(border, 'You should send valid hex strings.') break if len(s1) == len(s2) == 35 - level and s1 != s2: if vinefruit(s1, mod, 1) == vinefruit(s2, mod, 1): if vinefruit(s1, mod, 1) notin S: S.append(vinefruit(s1, mod, 1)) pr(border, 'gj, try the next level :)') else: break else: break else: die(border, 'Kidding me?! Try again and be smart!! Bye!!!') elif ans == 'q': die(border, 'Quitting...') else: die(border, 'You should select valid choice!')
P = [16777619, 1099511628211, 309485009821345068724781371] O = [2166136261, 14695981039346656037, 144066263297769815596495629667062367629] p, o, m = P[mod], O[mod], 2 ** (2 << (4 + mod)) M = m
length = 35 - level P = PolynomialRing(ZZ, "ap", length) aps = P.gens() aa = [ap + avg for ap in aps] f = sum([a * p**(i+1) for i, a in enumerate(aa)]) + o - length
L = matrix(f.coefficients()).T L = block_matrix([[1,L],[0,M]]) scale = [1]*(length+1) + [2**20] Q = diagonal_matrix(scale) L *= Q L = L.BKZ(block_size=25) L /= Q
answer = []
for row in L: if row[-2] < 0: row = -row if row[-1] == 0and row[-2] == 1: #print(row) assert f(*row[:-2]) % M == 0 aa = [x + avg for x in row[:-2]][::-1] if bytes(aa).hex() notin answer: answer.append(bytes(aa).hex()) if len(answer) == 2: return answer from pwn import *
sh = remote("04.cr.yp.toc.tf","31777") sh.recvuntil("[Q]uit") sh.sendline("S") for level in range(19): sh.recvuntil("vinefruit(m1, ") mod = int(sh.recvuntil(",")[:-1]) answer = attack(mod,level) sh.recvuntil("string: ") sh.sendline(answer[0]) sh.recvuntil("string: ") sh.sendline(answer[1])
# [DEBUG] Received 0xcd bytes: # b'| gj, try the next level :)\n' # b'| Submit two different string such that vinefruit(m1, 0, 1) = vinefruit(m2, 0, 1)\n' # b'| You are at level: 19\n' # b"| Congrats, you got the flag: b'CCTF{fINd1n9_cOlL!s10n_f0r___FNV2___!}'\n"
E_start = EllipticCurve(Fp2, [0,6,0,1,0]) E_start.set_order((p+1)^2) # Speeds things up in Sage
# Generation of the endomorphism 2i two_i = generate_distortion_map(E_start)
# Generate public torsion points, for SIKE implementations # these are fixed but to save loading in constants we can # just generate them on the fly # P2, Q2, P3, Q3 = generate_torsion_points(E_start, a, b) P = (3799366067639160994711391413511701264777392349807255916259320256251336249666*i + 633884628131689177031068067897867565283026098415356709331881575255526844055, 3967348484864888240941807454988077684669074109524399477973520952727771366997*i + 2712354532382043232096058211997452093712477916671679907467703464009558475387) Q = (560486392227142181240528415381730657098132581407794833013161975335122628946*i + 3215971074127995409351672272900519761566156375365764079386358523254177565572, 2231746347912007096335360835242707156884468521076802738444724241125548841199*i + 1147378568798166954853288670809304301194478550602719730593160186622788033023) R = (2656280316115888204975052029900945854050191685154131031859911335618240136443*i + 1127449111197960889758916770042950976852995868310602942974825430779982061546, 3477289737920472771668877366806058236254602770820629911886593813749930497839*i + 4646016633241840360901490323351236375375727836768954121794139000985805816564) S = (2403139149412141532587482679318245468078604585804423116505024414375742701912*i + 2772488504607240668919423445309052101443116827322741849326656561794480962717, 3356599382898540527962106232860239304405841217130774924490318752448476310798*i + 2818004736373436361527915593539097434287090434842750370886675729711731978922) P2, Q2, P3, Q3 = E_start(P), E_start(Q), E_start(R), E_start(S)
check_torsion_points(E_start, a, b, P2, Q2, P3, Q3)
print(f"Running the attack against Baby SIDHp64 parameters, which has a prime: 2^{a}*3^{b} - 1") #print(f"If all goes well then the following digits should be found: {solution}")
defmain(): border = "|" pr(border*72) pr(border, "Hi all, I have created a basic and rudimentary version of a sumcheck", border) pr(border, "protocol. Your task is to generate a false statement and persuade ", border) pr(border, "verifier of its validity. ", border) pr(border*72) q = 2**61 - 1# Mersenne prime F = GF(q)
whileTrue: pr("| Options: \n|\t[C]laim the statement \n|\t[D]etermine parameters and polynomial \n|\t[Q]uit") ans = sc().decode().lower().strip() if ans == 'd': pr(border, f'Please first send the number of variable and the degree of your desired polynomial:') _ans = sc() try: _n, _d = [int(_) for _ in _ans.split(b',')] if (_n * _d) // q < 5e-17and _n >= 5and _d >= 3: R = PolynomialRing(F, _n, 'x') x = R.gens() else: raise Exception() except: die(border, 'The parameters are not consistent! Try again!!') pr(border, f'Now, please send the {_n}-variable polynomial as p: ') _p = sc().strip().decode() try: _p = R(_p) p = _p _deg = _p.degree(std_grading=True) if _deg != _d: raise Exception() except: die(border, 'The polynomial is not valid or does not hold true in the given situations!') g = slowsum(_p, _n) elif ans == 'c': pr(border, 'Please send the g: ') _g = sc() try: _g = int(_g) if _g == g: die(border, 'Kidding me?! Bye :P') except: die(border, 'Some exception occurred! Bye!!') _P, _H = [], [] for i in range(_n): pr(border, f'Please send the (p_{i}, h4sh(p_{i}, q)): ') pr(border, f'Note that the variable of p_{i} should be x. ') _ph = sc().strip() try: _p, _h = [_.decode() for _ in _ph.split(b',')] _R = PolynomialRing(F, 'x') _p, _h = _R(_p), F(_h) if _p.degree() > _d: raise Exception() _P.append(_p) _H.append(_h) except: die(border, 'Some exception occurred! Bye!!') j = 0 for i in range(_n): if i == 0: if _P[i](0) + _P[i](1) != _g or h4sh(_P[i], q) != _H[i]: break else: if _P[i](0) + _P[i](1) != _P[i-1](_H[i-1]) or h4sh(_P[i], q) != _H[i]: break j += 1 if j < _n or p(_H) != _P[_n-1](_H[_n-1]): die(border, 'Oops, verifier believes that the polynomial is not valid! Bye!!') die(border, f'Congrats, here the flag: {flag}') elif ans == 'q': die(border, 'Quitting...') else: die(border, 'You should select valid choice!')
if __name__ == '__main__': main()
这道题的流程看起来比较复杂冗长,我们一点点走下来。
首先看到 [D]etermine parameters and polynomial:我们需要给服务提供一个多项式,不过在此之前,我们要先如果这个多项式的变量数量和度(degree),其中,需要满足 if (_n * _d) // q < 5e-17 and _n >= 5 and _d >= 3:,那么我们这里就先设定 $n=5,d=3$ ,然后我们给出的多项式为 x0^3 (他好像只判断了最高次,并没有判断变量数量,所以方便起见,我们先给一项,往后看看先),然后执行 g = slowsum(_p, _n)
1 2 3 4 5 6
defslowsum(p, n): g = 0 perms = list(product([0, 1], repeat = n)) for _prm in perms: g += p(_prm) return g
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | Hi all, I have created a basic and rudimentary version of a sumcheck | | protocol. Your task is to generate a false statement and persuade | | verifier of its validity. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | Options: | [C]laim the statement | [D]etermine parameters and polynomial | [Q]uit d | Please first send the number of variable and the degree of your desired polynomial: 5,3 | Now, please send the 5-variable polynomial as p: x0^3 | Options: | [C]laim the statement | [D]etermine parameters and polynomial | [Q]uit c | Please send the g: 1 | Please send the (p_0, h4sh(p_0, q)): | Note that the variable of p_0 should be x. x^3,1 | Please send the (p_1, h4sh(p_1, q)): | Note that the variable of p_1 should be x. x^3,1 | Please send the (p_2, h4sh(p_2, q)): | Note that the variable of p_2 should be x. x^3,1 | Please send the (p_3, h4sh(p_3, q)): | Note that the variable of p_3 should be x. x^3,1 | Please send the (p_4, h4sh(p_4, q)): | Note that the variable of p_4 should be x. x^3,1 | Congrats, here the flag: b'CCTF{Rem3Mb3er_tH4t_F14t_5h4m1r_tR4nsf0rm4tiOn_n33Ds_A_g00D_r4Nd0m_Or4cLe!}'
from Crypto.Util.number import * from flag import flag
defbase(n, l): D = [] while n > 0: n, r = divmod(n, l) D.append(r) return''.join(str(d) for d in reversed(D)) or'0'
defasiv_prng(seed): l = len(seed) _seed = base(bytes_to_long(seed), 3) _l = len(_seed) R = [[getRandomRange(0, 3) for _ in range(_l)] for _ in range(_l**2)] S = [] for r in R: s = 0 for _ in range(_l): b = ((int(r[_]) + int(_seed[_])) % 3) % 2 s = s ^ b S.append(s) print(len(S)) return R, S
seed = flag.lstrip(b'CCTF{').rstrip(b'}') R, S = asiv_prng(seed)
f = open('output.txt', 'w') f.write(f'R = {R}\nS = {S}') f.close()